<?php

class YAMLDomDefinition
{

  public static function fromFile($file)
  {
    //if (! Session::getInstance()->has('domain')) {
      if (! sy_path_is_absolute($file)) {
        $file = Simplify::getConfig()->get('app_dir') . '/model/' . $file;
      }

      $s = Syml::read($file);

      $types = array();

      if (isset($s['types'])) {
        foreach ($s['types'] as $name => $def) {
          $types[$name] = SimpleDictionary::parseFrom($def);
        }
      }

      $domain = Domain::getInstance();

      $associations = array();
      $references = array();

      foreach ($s['objects'] as $name => $def) {
        $as = array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany');

        $is_aggregate = false;

        foreach ($as as $type) {
          if (isset($def[$type]) && is_array($def[$type])) {
            $is_aggregate = true;

            foreach ($def[$type] as $aname => $adef) {
              if (is_array($adef)) {
                $aparams = $adef[1];
                $adef = $adef[0];
              }

              list($e, $f) = explode('.', $adef);

              $associations[] = array_merge(array('source' => $name, 'name' => $aname, 'target' => $e, 'foreignKey' => $f, 'type' => $type,
                'single' => in_array($type, array('hasOne', 'belongsTo'))), isset($aparams) ? $aparams : array());
            }
          }
        }

        if ($is_aggregate) {
          $obj = new AggregateDefinition($name);
        }
        else {
          $obj = new EntityDefinition($name);
        }

        foreach ($def['fields'] as $fname => $fdef) {
          if (! isset($fdef['name'])) {
            $fdef['name'] = $fname;
          }

          if (isset($types[$fdef['type']])) {
            $type = new SimpleDictionary();
            $type->copyAll($types[$fdef['type']]);

            unset($fdef['type']);

            $fdef = $type->copyAll($fdef);
            $fdef = $fdef->getAll();
          }

          if (isset($fdef['references'])) {
            foreach (( array ) $fdef['references'] as $reference) {
              $references[$reference] = $fname;
            }
          }

          $field = new FieldDefinition($fdef);
          $obj->addField($fname, $field);
        }

        $domain->addObject($obj);
      }

      foreach ($associations as $association) {
        $a = new AssociationDefinition($association['name']);

        switch ($association['type']) {
          case 'hasOne' :
            $a->proxyClass = 'HasOneAssociation';
            break;

          case 'hasMany' :
            $a->proxyClass = 'HasManyAssociation';
            break;

          case 'belongsTo' :
            $a->proxyClass = 'BelongsToAssociation';
            break;

          case 'hasAndBelongsToMany' :
            $a->proxyClass = 'HABTMAssociation';
            $a->associationTable = sy_get_param($association, 'associationTable');
            $a->associationPrimaryKey = sy_get_param($association, 'associationPrimaryKey');
            $a->associationForeignKey = sy_get_param($association, 'associationForeignKey');
            break;
        }

        $a->source = $domain->getObject($association['source']);
        $a->target = $domain->getObject($association['target']);

        $reference = $association['source'] . '.' . $association['name'];

        if (isset($references[$reference])) {
          $a->primaryKey = $references[$reference];
          $a->primaryKeyField = $a->source->getField($references[$reference]);
        }
        else {
          $a->primaryKey = $a->source->getPk();
          $a->primaryKeyField = $a->source->getPkField();
        }

        $a->foreignKey = $association['foreignKey'];
        $a->foreignKeyField = $a->target->getField($association['foreignKey']);

        $a->required = sy_get_param($association, 'required');
        $a->single = $association['single'];

        $a->source->addAssociation($association['name'], $a);
      }

      if (! empty($s['repositories'])) {
        foreach ($s['repositories'] as $name => $def) {
          $domain->repositories[$name] = $def;
        }
      }
    //}
  }

}

?>